package com.wangwenjun.concurrency.chapter14.blockingqueue;

import org.junit.Test;

import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * @Package: com.wangwenjun.concurrency.chapter14.blockingqueue
 * @ClassName: UseLinkedBlockingQueue
 * @Author: lujieni
 * @Description: 1
 * @Date: 2021-03-10 16:07
 * @Version: 1.0
 *
 *  LinkedBlockingQueue
 *  1.可选有界,如果没有指定则为Integer.MAX
 *  2.先进先出
 *  3.线程安全
 *  4.提供put和take的阻塞api
 *  6.LinkedBlockingQueue中使用入列锁和出列锁的分离,故LinkedBlockingQueue的并发执行效率要高一些
 *
 */
public class UseLinkedBlockingQueue {

    /**
     *
     * add方法超过队列容量会直接抛异常
     *
     */
    @Test
    public void testAdd(){
        LinkedBlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<>(3);

        System.out.println(blockingQueue.add(1));
        System.out.println(blockingQueue.add(2));
        System.out.println(blockingQueue.add(3));

        // IllegalStateException: Queue full 抛出异常
        blockingQueue.add(4);
    }

    /**
     * remove如果队列为空会抛异常,和add类似
     */
    @Test
    public void testRemove(){
        Queue<Integer> blockingQueue = new LinkedBlockingQueue<>(3);

        System.out.println(blockingQueue.add(1));
        System.out.println(blockingQueue.add(2));
        System.out.println(blockingQueue.add(3));

        blockingQueue.remove();
        blockingQueue.remove();
        blockingQueue.remove();
        blockingQueue.remove();

    }

    /**
     * offer方法超过队列容量会直接返回false,并不会抛异常
     */
    @Test
    public void testOffer(){
        Queue<Integer> blockingQueue = new LinkedBlockingQueue<>(3);

        System.out.println(blockingQueue.offer(1));
        System.out.println(blockingQueue.offer(2));
        System.out.println(blockingQueue.offer(3));

        System.out.println(blockingQueue.offer(4));
    }

    /**
     * poll队列为空会返回null, 不会抛异常
     */
    @Test
    public void testPoll(){
        LinkedBlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<>(3);

        System.out.println(blockingQueue.offer(1));
        System.out.println(blockingQueue.offer(2));
        System.out.println(blockingQueue.offer(3));

        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
    }

    /**
     * put方法超过队列容量会直接阻塞
     */
    @Test
    public void testPut() throws InterruptedException {
        LinkedBlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<>(3);
        blockingQueue.put(1);
        blockingQueue.put(2);
        blockingQueue.put(3);
        blockingQueue.put(4);
    }

    @Test
    public void testTake() throws InterruptedException {
        LinkedBlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<>(3);
        blockingQueue.put(1);
        blockingQueue.put(2);
        blockingQueue.put(3);


        blockingQueue.take();
        blockingQueue.take();
        blockingQueue.take();
        blockingQueue.take();
    }


    /**
     * Retrieves, but does not remove, the head of this queue, or returns null if this queue is empty.
     * Returns:
     * the head of this queue, or null if this queue is empty
     *
     * peek只看队首元素是啥但不移除元素,如果队列为空返回null
     */
    @Test
    public void testPeek(){
        LinkedBlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<>(3);

        System.out.println(blockingQueue.offer(1));
        System.out.println(blockingQueue.offer(2));
        System.out.println(blockingQueue.offer(3));

        System.out.println(blockingQueue.peek());
        System.out.println(blockingQueue.peek());
        System.out.println(blockingQueue.peek());
        System.out.println(blockingQueue.peek());
        System.out.println(blockingQueue.peek());
    }

}